<?php
/**
 * Created by PhpStorm.
 * User: henly
 * Date: 14-4-18
 * Time: 下午4:29
 * E-mail: huwenlong_92@hotmail.com
 */
class curl{

    //对象单例
    static $_instance = null;

    //需要发送的cookies信息
    private $cookies = '';

    //需要发送的头信息
    private $header = array();
    // 需要访问的URL地址
    private $uri = '';

    //需要发送的数据
    private $vars = array();
    //端口号
    private $port = '';
    //设置连接超时时限    单位秒
    private $timeout = 10;

    /**
     * 构造器
     * @param $url
     * @param int $port
     */
    private function  __construct($url,$port = 0 ){
        $this->uri = $url;
        $this->port = $port;
    }

    /**
     * 保证对象不被clone
     */
    private function __clone(){}

    /**
     *  获取对象唯一实例
     * @param string $url
     * @param int $port
     * @return curl|null
     */
    public static  function getInstance($url = '',$port = 80){
        if(!(self::$_instance instanceof self)){
            self::$_instance = new self($url,$port);
        }
        return self::$_instance;
    }

    /**
     *  生成一个供Cookie 或 HTTP GET QUERY 的字符串
     *     如 : param = 1 & param = 2  ....
     * @param $data
     * @param string $sep
     * @return string
     */
    public static function makeQuery($data,$sep = '&'){
        $encoded = '';
        if(!empty($data)){
            foreach($data as $key => $val){
                $encoded .= ($encoded ? "$sep" : "");
                $encoded .= $key . "=" . urlencode($val);
            }
        }
        return $encoded;
    }

    /**
     *  设置Cookie 头信息
     * @param $cookies
     * @return string
     */
    public function setCookie($cookies){
        if(empty($cookies)){
            return ;
        }
        if(is_array($cookies)){
            $this->cookies = self::makeQuery($cookies,';');
        }else if(is_string($cookies)){
            $this->cookies = $cookies;
        }
    }

    /**
     *  设置需要发送的HTTP 头信息
     * @param $header
     *      $header = array('Host: example.com', 'Accept-Language: zh-cn')
     *      $header = 'Host: example.com'
     */
    public function setHeader($header){
        if(empty($header)){
            return ;
        }
        if(is_array($header)){
            foreach($header as $key => $val){
                $this->header[] = is_numeric($key) ? trim($val) : (trim($key) . ': ' . trim($val));
            }
        }else if(is_string($header)){
            $this->header[] = $header;
        }
    }

    /**
     *  设置要请求的URL地址
     * @param $url
     */
    public function setUrl($url){
        if(!empty($url)){
            $this->uri = $url;
        }
    }

    /**
     *  设置端口号
     * @param $port
     */
    public function setPort($port){
        if(intval($port) > 0){
            $this->port = intval($port);
        }
    }

    /**
     *  设置超时时限
     * @param $timeout
     */
    public function setTimeout($timeout = 10){
        if($timeout != $this->timeout){
            $this->timeout = $timeout;
        }
    }

    /**
     *  设置要发送的参数
     * @param array $vars
     */
    public function setParam(array $vars = null){
        if(empty($vars)){
            return ;
        }
        if(!is_null($vars)){
            $this->vars = $vars;
        }
    }

    /**
     *  发送GET请求
     * @param string $url
     * @param array $vars
     * @param array $header
     * @param string $cookie
     * @param int $timeout
     * @param array $options
     * @param int $port
     * @return mixed
     */
    public function get($url = '',$vars = array(),$header = array(),$cookie = '',$timeout = 10,$options = array(),$port = 0){
        $this->setUrl($url);
        $this->setHeader($header);
        $this->setCookie($cookie);
        $this->setParam($vars);
        $this->setPort($port);
        return $this->send('GET',$timeout);
    }

    /**
     *  发送POST请求
     * @param string $url
     * @param array $vars
     * @param array $header
     * @param string $cookie
     * @param int $timeout
     * @param array $options
     * @param int $port
     * @return mixed
     */
    public function post($url = '',$vars = array(),$header = array(),$cookie = '',$timeout = 10,$options = array(),$port = 0){
        $this->setUrl($url);
        $this->setHeader($header);
        $this->setCookie($cookie);
        $this->setParam($vars);
        $this->setPort($port);
        return $this->send('POST',$timeout);
    }


    public function send($method = 'GET',$timeout = 10,$options = array()){
        //处理参数是否为空
        if(empty($this->uri)){
            throw new Exception('Access url is empty',__CLASS__);
        }

        //初始化CURL
        $ch = curl_init();
        curl_setopt($ch,CURLOPT_HEADER,0);
        curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
        if(empty($this->timeout) && !is_numeric($timeout)){
            $timeout = $this->timeout;
        }
        //设置超时时限
        curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);
        //设置特殊属性
        if(!empty($options)){
            curl_setopt_array($ch,$options);
        }
        if($method == 'GET'){
            //处理GET请求参数
            if(!empty($this->vars)){
                $query = self::makeQuery($this->vars);
                $parse = parse_url($this->uri);
                $sep = isset($parse['query']) ? '&' : '?';
                $this->uri .= $sep . $query;
            }
        }elseif($method == 'POST'){
            //处理POST请求参数
            curl_setopt($ch,CURLOPT_POST,1);
            if(!empty($this->vars)){
                curl_setopt($ch,CURLOPT_POSTFIELDS,$this->vars);
            }
        }

        //设置Cookie信息
        if(! empty($this->cookies)){
            curl_setopt($ch,CURLOPT_COOKIE,$this->cookies);
        }

        //设置HTTP缺省头
        if(empty($this->header)){
            $this->header = array(
                'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)',
                'Accept-Language: zh-cn',
                'Cache-Control: no-cache'
            );
        }
        curl_setopt($ch,CURLOPT_HTTPHEADER,$this->header);
        if($this->port){
            curl_setopt($ch,CURLOPT_PORT,$this->port);
        }
        //发送请求读取数据
        curl_setopt($ch,CURLOPT_URL,$this->uri);
        $data = curl_exec($ch);
        $err = curl_errno($ch);
        if($err){
            curl_close($ch);
            throw new Exception(__CLASS__,' Error: ',$err);
        }
        curl_close($ch);
        return $data;
    }



}